package com.j.lemon.learn.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author lijunjun
 * @Date 2019-03-18 16:14
 * @Description
 */
public class VolatileTest {
    private static volatile int num;
    private static final ExecutorService executorService = Executors.newFixedThreadPool(10);

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            executorService.execute(new ThreadTest());
        }
        executorService.shutdown();
        System.out.println(num);
    }

    static class ThreadTest implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10000; i++) {
                //下面这行代码会有如下提示：Non-atomic operation on volatile field 'num'
                //解释：volatile只能保证可见性，即每当线程++之前，读取到的都是其他线程写入后的值，
                //但是当多个线程一起读取的时候，num的值时一样的，然后，都进行++ ，结果会不准确
                //volatile使用场景，只进行set或者get操作时，见VolatileTest1类
                num++;
            }
        }
    }
}

/**
 * 单例模式
 */
class VolatileTest1{
    private static VolatileTest1 instance;
    public static VolatileTest1 getInstance(){
        if(instance==null){
            synchronized (VolatileTest1.class){
                if(instance==null){
                    instance = new VolatileTest1();
                }
            }
        }
        return instance;
    }
}

/**
 * 该程序会一致执行下去，因为线程读取到的flag一直为true，虽然后面修改成了false，但是对于当前线程不可见，使用volatile可以解决此类标志位问题
 */
class VolatileTest2{
    private static int num;
    private static boolean flag=true;

    private static class ThreadTest extends Thread{
        @Override
        public void run() {
            while(flag){
                num++;
//                System.out.println("继续添加");
            }
            System.out.println(num);
        }
    }
    public static void main(String[] args) throws InterruptedException {
        new ThreadTest().start();
        Thread.sleep(1000);
        flag=false;
    }

}
